<html>
<head><meta charset="utf-8"><title>Padding · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html">Padding</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="213139376"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213139376" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213139376">(Oct 13 2020 at 11:12)</a>:</h4>
<p>I just noticed <a href="https://lists.llvm.org/pipermail/llvm-dev/2020-October/145692.html">this discussion on LLVM</a> where they say that padding in C is "less undefined" that uninit memory. That is news to me. So far I was working under the assumption (for Rust) that padding is like uninit memory.</p>



<a name="213139955"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213139955" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213139955">(Oct 13 2020 at 11:20)</a>:</h4>
<p>C18, 6.2.6.1 §6 says</p>
<blockquote>
<p>When a value is stored in an object of structure or union type, including in a member object, the<br>
bytes of the object representation that correspond to any padding bytes take unspecified values.</p>
</blockquote>
<p>an unspecified value is a "valid value of the relevant type where this International Standard imposes no requirements on which value is chosen in any instance".  padding has no type though so what is "the relevant type"?</p>
<p>OTOH, the footnote for memcmp says</p>
<blockquote>
<p>The contents of “holes” used as padding for purposes of alignment within structure objects are indeterminate.</p>
</blockquote>
<p>Footnotes are not normative but this still indicates some confusion...</p>



<a name="213140147"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213140147" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213140147">(Oct 13 2020 at 11:22)</a>:</h4>
<p>Something seems wrong when in an uninitialized <code>(u8, u16)</code>, there are more guarantees made about the padding byte than about the integers...</p>



<a name="213142160"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213142160" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213142160">(Oct 13 2020 at 11:47)</a>:</h4>
<p>Certainly in the current Rust implementation you can even get LLVM to optimize a read of padding types into <code>undef</code>.</p>
<p>Do the clang folks initialize structures to something other than undef?</p>



<a name="213143409"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213143409" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jake Goulding <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213143409">(Oct 13 2020 at 12:01)</a>:</h4>
<blockquote>
<p>padding has no type though </p>
</blockquote>
<p>Without reading anything other than what you’ve written, are you sure about this?</p>



<a name="213228455"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213228455" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213228455">(Oct 13 2020 at 23:06)</a>:</h4>
<p>is it to allow memcpy implementations (and the like) to perform wider reads without risking the reads becoming UB because of pulling in padding bytes? if it's not uninit and just unspecified wouldn't it behave appropriately for a copy?</p>



<a name="213228876"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213228876" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213228876">(Oct 13 2020 at 23:11)</a>:</h4>
<p>oh wait I think it's considered non-ABI breaking in C to insert a new field into what was previously padding bytes of a struct</p>



<a name="213229083"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213229083" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213229083">(Oct 13 2020 at 23:14)</a>:</h4>
<p>non-ABI-breaking in practice.  I don't think it's actually allowed by the spec though, or at least doing so would have serious limitations.  By the clause Ralf quoted, old code that modified any member would put unspecified values into the padding bytes.  In practice that can happen if a smaller store is widened.</p>



<a name="213229225"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213229225" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213229225">(Oct 13 2020 at 23:15)</a>:</h4>
<p>right, i wasn't sure who exactly declared it that way (i don't think the C standard says much about ABI compat), and the precise details. I agree padding being merely unspecified and not UB is surprising, (although honestly it's preferrable if you ask me)</p>



<a name="213229566"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213229566" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213229566">(Oct 13 2020 at 23:19)</a>:</h4>
<p>Yeah, both the C++ standard (One-Definition Rule) and the C standard require struct definitions to be exactly the same between all translation units.</p>



<a name="213229649"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213229649" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213229649">(Oct 13 2020 at 23:20)</a>:</h4>
<p>Leaving ABI compatibility as one of those things that people depend on despite technically being UB.</p>



<a name="213230177"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213230177" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> comex <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213230177">(Oct 13 2020 at 23:28)</a>:</h4>
<p><a href="https://gcc.godbolt.org/z/3evKf1">https://gcc.godbolt.org/z/3evKf1</a> &lt;- Looks like Clang doesn't do anything special to initialize padding, so if you start with an uninitialized struct and fill in all the non-padding members, the padding stays <code>undef</code>.  Though if you initialize it (<code>union u u = {}</code>), it memsets the whole thing to 0, including padding.  And it stays as 0, because I can't get it to actually widen writes or otherwise take advantage of "padding bytes take unspecified values".</p>



<a name="213230700"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213230700" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213230700">(Oct 13 2020 at 23:34)</a>:</h4>
<p>the impression i got was that clang might be currently miscompiling padding as undef in some cases? But I don't really know.</p>



<a name="213230847"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213230847" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213230847">(Oct 13 2020 at 23:37)</a>:</h4>
<p>(in practice i can wait for inline asm to perform widened operations like that — and i'm happy to even have that)</p>



<a name="213643907"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213643907" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213643907">(Oct 17 2020 at 09:46)</a>:</h4>
<p>I guess one question I have here is -- would people consider it reasonable if, no matter what LLVM did, Rust would say that padding is uninit memory, i.e., UB to even "look at"? that seems much more consistent to me, and also is much easier to define...</p>



<a name="213644623"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213644623" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213644623">(Oct 17 2020 at 10:07)</a>:</h4>
<p>Would there be an analogue to <code>freeze</code> in the rust semantics?</p>



<a name="213644696"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213644696" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213644696">(Oct 17 2020 at 10:09)</a>:</h4>
<p>maybe, but see <a href="https://github.com/rust-lang/rfcs/pull/837">https://github.com/rust-lang/rfcs/pull/837</a> for some good arguments against that</p>



<a name="213675402"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213675402" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213675402">(Oct 17 2020 at 23:14)</a>:</h4>
<p>I think that if you need <code>MaybeUninit</code> for even <code>undef</code> in <code>u8</code>, then it also being needed to hold padding would make sense to me</p>



<a name="213745837"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213745837" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213745837">(Oct 19 2020 at 05:56)</a>:</h4>
<blockquote>
<p>that seems much more consistent to me, and also is much easier to define...</p>
</blockquote>
<p>Possibly, but it also increases the severity of bugs of code that looks at it, which IMO is undesirable. There are also cases where you'd like to be able to do this where there isn't a great alternative if padding bytes are UB to look at (consider cases like an Atomic&lt;T&gt; that boils down to an atomic int for sufficiently small T)</p>



<a name="213847924"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213847924" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213847924">(Oct 19 2020 at 21:21)</a>:</h4>
<p><code>AtomicMaybeUninit{Int}</code> when <span aria-label="big smile" class="emoji emoji-1f604" role="img" title="big smile">:big_smile:</span></p>



<a name="213855518"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213855518" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213855518">(Oct 19 2020 at 22:41)</a>:</h4>
<p>I don't think that would actually solve it tho</p>



<a name="213894185"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213894185" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213894185">(Oct 20 2020 at 09:29)</a>:</h4>
<p>I mean, it would be a pain, but if <code>AtomicMaybeUninit{Int}</code> was possible to implement (I don't know if LLVM would allow such an op), then you could afterwards read the init bytes out of your local read:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">//! AtomicCell&lt;ReprCTuple2&lt;u8, /* u8_pad, */ u16&gt; (: Copy)&gt;</span>
<span class="kd">let</span><span class="w"> </span><span class="n">chunk</span>: <span class="nc">MaybeUninit</span><span class="o">&lt;</span><span class="kt">u32</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">at_atomic_maybe_uninit_32</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">Ordering</span>::<span class="o">..</span><span class="p">.);</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">it</span>: <span class="nc">ReprCTuple2</span><span class="o">&lt;</span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="kt">u16</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">transmute</span><span class="p">(</span><span class="n">chunk</span><span class="p">);</span><span class="w"></span>
</code></pre></div>

<p>But I can imagine atomic ops on uninit bytes not being a possibility <span aria-label="grimacing" class="emoji emoji-1f62c" role="img" title="grimacing">:grimacing:</span></p>
<p>EDIT: And you actually don't even need <code>repr(C)</code>, provided you only use actual instances to be stored inside the <code>AtomicMaybeUninit{Int}</code></p>



<a name="213996551"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/213996551" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#213996551">(Oct 21 2020 at 00:40)</a>:</h4>
<p>I believe that <code>MaybeUninit&lt;int&gt;</code> is still all or nothing for initialization, e.g. transmuting the chunk there is UB</p>



<a name="214340371"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding/near/214340371" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Padding.html#214340371">(Oct 23 2020 at 17:15)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Padding/near/213996551">said</a>:</p>
<blockquote>
<p>I believe that <code>MaybeUninit&lt;int&gt;</code> is still all or nothing for initialization, e.g. transmuting the chunk there is UB</p>
</blockquote>
<p>we'd want it to not be, but LLVM <code>poison</code>might be all-or-nothing for types like <code>i32</code> and due to <code>repr(transparent)</code> that's how <code>MaybeUninit&lt;i32&gt;</code> is compiled... :/</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>